package cz.muni.fi.pv168.ContactManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Vlado
 * Date: 4.3.2012
 * Time: 17:20
 * To change this template use File | Settings | File Templates.
 */
public class AddressBookManagerImpl implements AddressBookManager {

    private DataSource dataSource;

    final static Logger log = LoggerFactory.getLogger(AddressBookManagerImpl.class);

    public void setDataSource(DataSource ds)
    {
        this.dataSource = ds;
    }

    @Override
    public void addContactToPerson(Person person, Contact contact) {
        if(dataSource == null) throw new IllegalStateException("Data source is not set!");
        if(contact == null) throw new NullPointerException("contact");
        if(contact.getId() == null) throw new IllegalEntityException("Id is null!");
        if(person == null) throw new NullPointerException("person");
        if(person.getId() == null) throw new IllegalEntityException("Id is null!");
        Connection conn = null;
        PreparedStatement st = null;
        try {
            conn = dataSource.getConnection();
            st = conn.prepareStatement(
                    "UPDATE CONTACT SET PERSONID = ? WHERE ID = ?");
            st.setLong(1, person.getId());
            st.setLong(2, contact.getId());

            int count = st.executeUpdate();
            if (count != 1)
            {
                String msg = "Error when updating contact in db";
                log.error(msg);
                throw new ServiceFailureException(msg);
            }
        } catch (SQLException ex) {
            String msg = "Error when updating contact in db";
            log.error(msg,ex);
            throw new ServiceFailureException(msg, ex);
        } finally {
            try {if(st != null) {st.close();}}
            catch (SQLException ex) {log.error("Error when closing statement", ex);}
            try {if(conn != null) {conn.close();}}
            catch (SQLException ex) {log.error("Error when closing connection", ex);}
        }
    }

    @Override
    public void removeContactToPerson(Person person, Contact contact) {
        if(dataSource == null) throw new IllegalStateException("Data source is not set!");
        if(contact == null) throw new NullPointerException("contact");
        if(contact.getId() == null) throw new IllegalEntityException("Id is null!");
        if(person == null) throw new NullPointerException("person");
        if(person.getId() == null) throw new IllegalEntityException("Id is null!");
        Connection conn = null;
        PreparedStatement st = null;
        try {
            conn = dataSource.getConnection();
            st = conn.prepareStatement(
                    "UPDATE CONTACT SET PERSONID = NULL WHERE ID = ? AND PERSONID = ?");
            st.setLong(1, contact.getId());
            st.setLong(2, person.getId());

            int count = st.executeUpdate();
            if (count != 1)
            {
                String msg = "Error when updating contact in db";
                log.error(msg);
                throw new ServiceFailureException(msg);
            }
        } catch (SQLException ex) {
            String msg = "Error when updating contact in db";
            log.error(msg,ex);
            throw new ServiceFailureException(msg, ex);
        } finally {
            try {if(st != null) {st.close();}}
            catch (SQLException ex) {log.error("Error when closing statement", ex);}
            try {if(conn != null) {conn.close();}}
            catch (SQLException ex) {log.error("Error when closing connection", ex);}
        }
    }

    @Override
    public List<Contact> getContactsToPerson(Person person) {
        if(dataSource == null) throw new IllegalStateException("Data source is not set!");
        if(person == null) throw new NullPointerException("person");
        if(person.getId() == null) throw new IllegalEntityException("Id is null!");

        Connection conn = null;
        PreparedStatement st = null;
        try {
            conn = dataSource.getConnection();
            st = conn.prepareStatement(
                    "SELECT ID, CONTACTTYPE, CONTACTVALUE FROM CONTACT WHERE PERSONID = ?");
            st.setLong(1,person.getId());
            ResultSet rs = st.executeQuery();
            List<Contact> result = new ArrayList<Contact>();
            while (rs.next()) {
                result.add(rowToContact(rs));
            }
            return result;
        } catch (SQLException ex) {
            String msg = "Error when getting contacts from db";
            log.error(msg,ex);
            throw new ServiceFailureException(msg, ex);
        } finally {
            try {if(st != null) {st.close();}}
            catch (SQLException ex) {log.error("Error when closing statement", ex);}
            try {if(conn != null) {conn.close();}}
            catch (SQLException ex) {log.error("Error when closing connection", ex);}
        }
    }

    private static Contact rowToContact(ResultSet rs) throws SQLException {
        Contact result = new Contact();
        result.setId(rs.getLong("ID"));
        result.setType(rs.getString("CONTACTTYPE"));
        result.setValue(rs.getString("CONTACTVALUE"));
        return result;
    }
}
